﻿#region [ License information          ]
/* ************************************************************
 *
 * Copyright (c) Bjørn Bouet Smith, 2010, 2011
 *
 * This source code is subject to terms and conditions of 
 * Microsoft Public License (Ms-PL).
 * 
 * A copy of the license can be found in the license.txt
 * file at the root of this distribution. If you can not 
 * locate the License, please send an email to bjornsmith@gmail.com
 * 
 * By using this source code in any fashion, you are 
 * agreeing to be bound by the terms of the Microsoft 
 * Permissive License.
 *
 * You must not remove this notice, or any other, from this
 * software.
 *
 * ************************************************************/
#endregion

using System.Configuration;

namespace Smith.AMC.Configuration
{
    /// <summary>
    /// Represents a memcached client configuration
    /// <configSections>
    ///    <section name="Smith.AMC" type="Smith.AMC.MemcachedClientConfiguration, Smith.AsyncMemcachedClient, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" allowDefinition="Everywhere" allowExeDefinition="MachineToApplication" restartOnExternalChanges="true" />
    /// </configSections>
    /// 
    /// <smith.amc socketpooltimeout="10" reconnectperiod="10" useudp="true" numberofsockets="25">
    ///     <servernodes>
    ///         <add hostname="127.0.0.1" tcpport="11211" udpport="11212" />
    ///         <add hostname="127.0.0.1" tcpport="11222" udpport="11212" />
    ///     </servernodes>
    /// </smith.amc>
    /// </summary>
    public class MemcachedClientConfiguration : ConfigurationSection
    {
        /// <summary>
        /// Gets the memcached nodes that participate in the server cluster
        /// </summary>
        [ConfigurationProperty("servernodes", IsDefaultCollection = false)]
        public MemcachedNodeCollection MemcachedNodes
        {
            get
            {
                MemcachedNodeCollection nodeCollection = (MemcachedNodeCollection)base["servernodes"];
                return nodeCollection;
            }
        }

        /// <summary>
        /// Gets the monitor configuration.
        /// </summary>
        /// <value>The monitor configuration.</value>
        [ConfigurationProperty("monitorconfiguration", IsRequired = false)]
        public ServerNodeMonitorConfiguration MonitorConfiguration
        {
            get
            {
                ServerNodeMonitorConfiguration config = (ServerNodeMonitorConfiguration)base["monitorconfiguration"];
                return config;
            }
        }

        /// <summary>
        /// Gets or sets the timeout period in seconds in waiting for a vacant socket from the socket pool.
        /// default value is 5 seconds, which is a very long time to wait for a socket.
        /// </summary>
        [ConfigurationProperty("socketpooltimeout", IsRequired = false, DefaultValue = 5)]
        [IntegerValidator(MinValue = 1, MaxValue = 100)]
        public int ConnectionTimeout
        {
            get
            {
                return (int)this["socketpooltimeout"];
            }
            set
            {
                this["socketpooltimeout"] = value;
            }
        }

        /// <summary>
        /// Gets or sets the delay in seconds between the client trying to reconnect to a server node that has been
        /// marked as dead
        /// default value is 10 seconds, which is not a very long time.
        /// </summary>
        [ConfigurationProperty("reconnectperiod", IsRequired = false, DefaultValue = 10)]
        [IntegerValidator(MinValue = 1, MaxValue = 600)]
        public int ReconnectPeriod
        {
            get
            {
                return (int)this["reconnectperiod"];
            }
            set
            {
                this["reconnectperiod"] = value;
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether to use the UDP protocol for GET operations.
        /// against the server.
        /// UDP has the advantage that it does not have to hold a connection to the server.
        /// Making it more scalable.
        /// Tthe disadvantage is that there are no delivery guarantee on UDP, so cache gets
        /// will probably miss from time to time.
        /// </summary>
        [ConfigurationProperty("useudp", IsRequired = false, DefaultValue = "False")]
        public bool UseUdp
        {
            get
            {
                return (bool)this["useudp"];
            }
            set
            {
                this["useudp"] = value;
            }
        }


        /// <summary>
        /// Gets or sets the number of sockets the client should open to each server.
        /// Sockets will be opened on a need basis, but as soon as they have been opened, they
        /// stay open until the client shuts down.
        /// If you have many client instances, keep the number of connections low, but if you have few client instances
        /// you can safely set the number of sockets to a higher number.
        /// The important part is to not run out of sockets on the client machine, since the client will
        /// open the number of sockets to each server in the cluster.
        /// </summary>
        [ConfigurationProperty("numberofsockets", IsRequired = false, DefaultValue = 25)]
        [IntegerValidator(MinValue = 1, MaxValue = 100)]
        public int NumberOfSockets
        {
            get
            {
                return (int)this["numberofsockets"];
            }
            set
            {
                this["numberofsockets"] = value;
            }
        }
    }
}
